package org.datascooter.generator;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.datascooter.bundle.DSMapper;
import org.datascooter.exception.EntityNotMappedException;
import org.datascooter.impl.DataManager;
import org.datascooter.inface.IDataManager;
import org.datascooter.utils.DSSettings;
import org.datascooter.utils.policy.SequencePolicy;

public class IdManager {

	public static final String DS_GLOBAL = "DS_GLOBAL";
	private Map<String, DSCounter> idMap = new ConcurrentHashMap<String, DSCounter>();
	private SequencePolicy sequencePolicy;
	private DSCounter global;
	private IDataManager dataManager;

	public IdManager(DataManager dataManager) {
		this.dataManager = dataManager;
		sequencePolicy = DSSettings.getSequencePolicy();
	}

	public void init() throws EntityNotMappedException, SecurityException, NoSuchMethodException {
		if (!sequencePolicy.equals(SequencePolicy.NO_SEQUENCES)) {
			if (dataManager.tableExists(DSMapper.getBundle(DSCounter.class))) {
				List<DSCounter> list = dataManager.list(DSCounter.class);
				for (DSCounter item : list) {
					item.setDataManager(dataManager);
					item.reborn();
					if (item.getName().equals(DS_GLOBAL)) {
						global = item;
					} else {
						idMap.put(item.getName(), item);
					}
				}
				if (global == null) {
					global = new DSCounter(DS_GLOBAL, dataManager);
					dataManager.save(global);
				}
			} else {
				dataManager.verifyTable(DSMapper.getBundle(DSCounter.class));
				global = new DSCounter(DS_GLOBAL, dataManager);
				dataManager.save(global);
			}
		}
	}

	public Long getId(String entity) {
		Long id = 0L;
		if (sequencePolicy.equals(SequencePolicy.GLOBAL)) {
			if (global == null) {
				global = new DSCounter(DS_GLOBAL, dataManager);
				dataManager.save(global);
			}
			id = global.use();
		} else if (sequencePolicy.equals(SequencePolicy.PER_TABLE)) {
			DSCounter counter = idMap.get(entity);
			if (counter == null) {
				counter = new DSCounter(entity, dataManager);
				dataManager.save(counter);
				idMap.put(entity, counter);
			}
			id = counter.use();
		}
		return id;
	}
}
